from sqlalchemy import event
from sqlalchemy.orm.attributes import get_history
from sqlmodel import Field, Relationship, SQLModel
from starlette.exceptions import HTTPException

from app.auth.models.permissions import GenericPermissions
from app.auth.models.utils import (
    create_permissions_for_model,
    delete_permissions_for_model,
)
from app.core.handlers.database import SessionBackend
from app.core.handlers.loggers import logger


class AppModelBase(SQLModel):
    app_label: str = Field(default=None, nullable=False, max_length=100)
    model_name: str = Field(
        default=None, nullable=False, max_length=100, regex=r"^[a-zA-Z][a-zA-Z0-9_]*$"
    )


class AppModelCreate(AppModelBase): ...


class AppModelPublic(AppModelBase): ...


class AppModel(AppModelBase, table=True):
    id: int = Field(primary_key=True)

    generic_permission: list[GenericPermissions] = Relationship(
        sa_relationship_kwargs={
            "primaryjoin": "and_(GenericPermissions.object_id==AppModel.id, foreign(GenericPermissions.content_type_id)==2)",
            "viewonly": True,
            "uselist": True,
        }
    )


# 监听 Model 模型的插入事件
@event.listens_for(AppModel, "after_insert")
def create_generic_permission(_mapper, connection, target):
    """
    当 Model 对象插入后，自动创建对应的 GenericPermissions 记录
    """
    db = SessionBackend(bind=connection)
    try:
        # 定义权限数据字典
        permissions_data = [
            {
                "code": f"table_{target.model_name}_!read",
                "description": f"禁止读取表 {target.model_name}",
            },
            {
                "code": f"table_{target.model_name}_!update",
                "description": f"禁止更新表 {target.model_name}",
            },
            {
                "code": f"table_{target.model_name}_!add",
                "description": f"禁止添加表 {target.model_name} 数据",
            },
            {
                "code": f"table_{target.model_name}_delete",
                "description": f"允许删除表 {target.model_name} 数据",
            },
        ]

        # 调用utils中的方法创建权限记录
        create_permissions_for_model(
            db, target, content_type_id=2, permissions=permissions_data
        )

    except Exception as e:
        db.rollback()
        logger.error(f"创建Model, model_name={target.model_name} 的通用权限时出错: {e}")
        raise HTTPException(status_code=500, detail="创建Model通用权限时出错")
    finally:
        db.close()


# 监听 Model 模型的更新事件
@event.listens_for(AppModel, "before_update")
def update_generic_permission(_mapper, _connection, target):
    """
    当 Model 对象更新前，检查是否修改了model_name字段
    如果修改了model_name字段，则抛出400错误
    如果没有修改model_name字段，则正常更新
    """
    # 检查model_name字段是否发生变化
    code_history = get_history(target, "model_name")
    if code_history.has_changes():
        # 如果model_name字段发生了变化，则抛出400错误
        raise HTTPException(
            status_code=400, detail="Model表model_name字段创建后不允许修改"
        )

    # 如果model_name字段没有变化，则允许正常更新
    # (不需要执行任何操作，更新会正常进行)


# 监听 Model 模型的删除事件
@event.listens_for(AppModel, "before_delete")
def delete_generic_permission(_mapper, connection, target):
    """
    当 Model 对象删除前，先删除相关的权限关联记录，再删除 GenericPermissions 记录
    """
    db = SessionBackend(bind=connection)
    try:
        delete_permissions_for_model(db, target, content_type_id=2)
    except Exception as e:
        db.rollback()
        logger.info(f"删除Model id={target.id}的通用权限时出错: {e}")
        raise HTTPException(status_code=500, detail="删除Model通用权限时出错")
    finally:
        db.close()